package puf.m2.regular;

public class TileRegExp extends RegExp {
    private static final long serialVersionUID = 1L;

    public TileRegExp() {
        super();
    }

    public TileRegExp(String string) {
        super(string);
    }

    public TileRegExp(TileRegExp exp) {
        super(exp);
    }

    /***** Implementations *****/

    protected boolean areThingsBalanced(String str) {
        int count = 0;
        int commaCount = 0;
        char ch;
        for (int i = 0; i < string.length(); i++) {
            ch = string.charAt(i);
            if (ch == '(')
                count++;
            else if (ch == ')')
                count--;
            else if (ch == ',')
                commaCount++;
            if (count < 0)
                return false;
        }
        return (count == 0 && commaCount % 2 == 0);
    }

    public String asCheckedString() throws UnsupportedOperationException {
        int length = string.length();
        if (length == 0)
            throw new UnsupportedOperationException(
                    "The expression must be nonempty.");
        if (!areThingsBalanced(string))
            throw new UnsupportedOperationException(
                    "The parentheses are unbalanced!");
        switch (string.charAt(0)) {
        case ')':
        case '+':
        case '*':
        case ',':
        case '~':
            throw new UnsupportedOperationException(
                    "Operators are poorly formatted.");
        }

        int commaCount = 0;
        int group_level = 0;
        boolean inverse_group = false;
        for (int i = 1; i < length; i++) {
            char c = string.charAt(i);
            char p = string.charAt(i - 1);
            switch (c) {
            case '(': // check tiles
                if (p == ',' || string.charAt(i + 1) == ',')
                    throw new UnsupportedOperationException(
                            "Tiles are wrongly formatted.");

                if (p == '~') inverse_group = true;
                group_level++;
                break;
            case '+':
                if (i == length - 1)
                    throw new UnsupportedOperationException(
                            "Operators are poorly formatted.");
            case '*':
                if (inverse_group)
                    throw new UnsupportedOperationException(
                            "Tiles are wrongly formatted.");
            case ')':
                if (p == '(' || p == '+' || p == ',' || p == '~')
                    throw new UnsupportedOperationException(
                            "Operators are poorly formatted.");
                if (!inverse_group) {
                    if (commaCount == 1) // insufficient comma to form a tile
                        throw new UnsupportedOperationException(
                                "Tiles are wrongly formatted.");
                }

                // only go to the next stmt if c is ')'
                if (c == '+' || c == '*')
                    break;

                if (commaCount == 2) {
                    commaCount = 0;
                }
                if (inverse_group)
                    inverse_group = false;
                group_level--;
                break;
            case '!':
                // TODO: fix this
                if (p != '(' && p != '+')
                    throw new UnsupportedOperationException(
                            "Lambda character must not cat with anything else.");
                if (i == length - 1)
                    break;
                p = string.charAt(i + 1);
                if (p != ')' && p != '+' && p != '*')
                    throw new UnsupportedOperationException(
                            "Lambda character must not cat with anything else.");
                break;
            case ',':
                if (inverse_group)
                    throw new UnsupportedOperationException(
                            "Tiles are wrongly formatted.");

                if (p == ',')
                    throw new UnsupportedOperationException(
                            "Tiles are wrongly formatted.");

                // a tile didn't begin with a left-parenthesis
                if (group_level < 1) {
                    throw new UnsupportedOperationException(
                            "Tiles are wrongly formatted.");
                }

                if (commaCount >= 2)
                    throw new UnsupportedOperationException(
                            "Tiles are wrongly formatted.");
                commaCount++;
                break;
            case '~':
                if (p == '~' || p == '+' || p == '*')
                    throw new UnsupportedOperationException(
                            "Tiles are wrongly formatted.");
                break;
             default:
                 // because we start from 1, so this handles the 0 position
                if (i == 1 && p == '(')
                    group_level++;

//                if (commaCount < 1)
//                    throw new UnsupportedOperationException(
//                            "Regular expression of single letter is not supported.");
                break;
            }
        }
        return string;
    }
}
